package com.fatmeraid.service.impl;

import com.fatmeraid.common.minio.MinioProperties;
import com.fatmeraid.service.FileService;
import io.minio.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 文件服务实现类，提供基于 MinIO 的文件上传功能。
 */
@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioProperties properties;

    /**
     * 上传文件到 MinIO 存储服务。
     *
     * @param file 要上传的文件，类型为 MultipartFile
     * @return 返回文件在 MinIO 中的完整访问 URL
     * @throws RuntimeException 当上传过程中发生异常时抛出运行时异常
     */
    @Override
    public String upload(MultipartFile file) {

        try {
            // 检查并创建存储桶（bucket）
            boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(properties.getBucketName()).build());
            if (!bucketExists){

                minioClient.makeBucket(MakeBucketArgs.builder().bucket(properties.getBucketName()).build());
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(properties.getBucketName()).config(createBucketPolicyConfig(properties.getBucketName())).build());
            }

            // 构造文件名：日期路径 + UUID + 原始文件名
            String filename = new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/" + UUID.randomUUID() + "-" + file.getOriginalFilename();

            // 上传文件到 MinIO
            minioClient.putObject(PutObjectArgs.builder()
                    .contentType(file.getContentType())
                    .bucket(properties.getBucketName())
                    .object(filename)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .build());

            // 构造并返回文件的完整访问地址
            return String.join("/", properties.getEndpoint(), properties.getBucketName(), filename);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建存储桶的访问策略配置，允许公共读取对象。
     *
     * @param bucketName 存储桶名称
     * @return 返回符合 AWS S3 格式的策略配置字符串
     */
    private String createBucketPolicyConfig(String bucketName) {

        return """
            {
              "Statement" : [ {
                "Action" : ["s3:GetObject", "s3:PutObject"],
                "Effect" : "Allow",
                "Principal" : "*",
                "Resource" : "arn:aws:s3:::%s/*"
              } ],
              "Version" : "2012-10-17"
            }
            """.formatted(bucketName);
    }
}
